package ch.myDungeons.game;

import java.io.Serializable;
import java.util.ArrayList;

import ch.myDungeons.characters.NPC;

/** 
 * A map of the game. Contains tiles and some check functions
 * @author Grii
 *
 */

public class Map implements Serializable {
	static final long serialVersionUID = 9854345678L;
	
	/** The tiles of the map */
	public Tile[][] tiles;
	
	/** all enemies on the map */
	public ArrayList<NPC> enemies;
	
	/** all NPCs on the map */
	public ArrayList<NPC> allies;

	public Map(int xSize, int ySize) {
		tiles = new Tile[xSize][ySize];
		for (int i = 0; i < tiles.length; i++) {
			for (int j = 0; j < tiles[i].length; j++) {
				tiles[i][j] = new Tile(true, i, j);
			}
		}
	}
	
	
	/** Check if the target tile is an obstacle */
	public boolean checkObstacle(int posX, int posY) {
		boolean result = false;
		if (!checkIsOnMap(posX, posY) || !tiles[posX][posY].accessible) { 
			result = true;
		}
		return result;
	}
	
	/** Check if the target tile is occupied by a character */
	public boolean checkOccupied(int posX, int posY) {
		boolean result = false;
		if (!checkObstacle(posX, posY) && tiles[posX][posY].personOnTheTile != null) {
			result = true;
		}
		return result;
	}

	/** Check if the target tile is occupied by an enemy */
	public boolean checkForEnemy(int posX, int posY) {
		boolean result = false;
		if(checkOccupied(posX, posY)){
			if(!tiles[posX][posY].personOnTheTile.isFriendly()){
				result = true;
			}
		}
		return result;
	}
	
	/** Check if the target tile is occupied by an ally */
	public boolean checkForAlly(int posX, int posY) {
		boolean result = false;
		if(checkOccupied(posX, posY)){
			if(tiles[posX][posY].personOnTheTile.isFriendly()){
				result = true;
			}
		}
		return result;
	}

	/** Check if the target tile is free to access */
	public boolean checkAccessability(int posX, int posY) {
		boolean result = false;
		if (!checkObstacle(posX, posY) && !checkOccupied(posX, posY)) {
			result = true;
		}
		return result;
	}
	
	/** Check if the target tile is free to access */
	public boolean checkIsOnMap(int posX, int posY) {
		boolean result = true;
		if (posX < 0 || posY < 0 || posX >= tiles.length || posY >= tiles[posX].length) { 
			result = false;
		}
		return result;
	}


	/** returns the location of the stairs. 0: stairs down x, 1: stairs down y, 2: stairs up x, 3: stairs up y */
	public int[] getStairs() {
		int[] result = new int[4];
		for (int x = 0; x < tiles.length; x++) {
			for (int y = 0; y < tiles[0].length; y++) {
				if (tiles[x][y].isStairsDown) {
					result[0] = x;
					result[1] = y;
				}
				if (tiles[x][y].isStairsUp) {
					result[2] = x;
					result[3] = y;
				}
			}
		}
		return result;
	}


	public String getSave() {
		String result = tiles.length + "<TILE>" + tiles[0].length;
		for (int i = 0; i < tiles[0].length; i++) {
			result += "<MAPLINE>";
			for (int j = 0; j < tiles.length; j++) {
				result += "\n<TILE>";
				result += tiles[j][i].getSave();
			}
		}
		return result;
	}
	
	/** Calculates the fields next to the person. result[0] is xPos, result[1] is yPos */
	public int[] getPostitionFromDirection(int direction, int posX, int posY){
		direction = (direction) % 4;
		int targetX = posX;
		int targetY = posY;
		
		switch (direction) {
		case 0: // North
			targetY -= 1;
			break;
		case 1: // East
			targetX += 1;
			break;
		case 2: // South
			targetY += 1;
			break;
		case 3: // West
			targetX -= 1;
			break;
		}
		
		return new int[] {targetX, targetY};
	}
}
